package net.sf.jimex.jira;

import com.atlassian.core.user.UserUtils;
import com.atlassian.jira.config.SubTaskManager;
import com.atlassian.jira.exception.CreateException;
import com.atlassian.jira.issue.IssueFactory;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.IssueUtilsBean;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.fields.AffectedVersionsSystemField;
import com.atlassian.jira.issue.fields.ComponentsSystemField;
import com.atlassian.jira.issue.fields.FixVersionsSystemField;
import com.atlassian.jira.issue.fields.PrioritySystemField;
import com.atlassian.jira.project.ProjectManager;
import com.atlassian.jira.security.JiraAuthenticationContext;
import com.opensymphony.user.EntityNotFoundException;
import com.opensymphony.user.User;
import org.apache.log4j.Logger;
import org.ofbiz.core.entity.GenericValue;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * andrew 19.03.2006 14:52:31
 */
public abstract class AbstractJiraIssuesManager implements JimexJiraIssuesManager {
    private static Logger logger = Logger.getLogger(AbstractJiraIssuesManager.class);

    protected IssueUtilsBean issueUtilsBean;
    protected IssueManager issueManager;
    protected ProjectManager projectManager;
    protected JiraAuthenticationContext authenticationContext;
    protected SubTaskManager subTaskManager;
    private IssueFactory issueFactory;
    protected Long projectId;
    private int issuetype;

    private ComponentsSystemField componentsSystemField;
    private FixVersionsSystemField fixVersionsSystemField;
    private AffectedVersionsSystemField affectedVersionsSystemField;
    private Map customFieldValuesHolder;
    private PrioritySystemField prioritySystemField;
    private String subTaskId;

    public AbstractJiraIssuesManager(IssueUtilsBean issueUtilsBean, IssueManager issueManager, ProjectManager projectManager, JiraAuthenticationContext authenticationContext, SubTaskManager subTaskManager, IssueFactory issueFactory) {
        this.issueUtilsBean = issueUtilsBean;
        this.issueManager = issueManager;
        this.projectManager = projectManager;
        this.authenticationContext = authenticationContext;
        this.subTaskManager = subTaskManager;
        this.issueFactory = issueFactory;
        this.subTaskId = null;
    }

    protected String createIssueInternal(String summary, String estimate, String assignee, String description, String parentIssueKey, int issueType) throws CreateException {
        MutableIssue mutableIssue = issueFactory.getIssue();
        GenericValue projectGenericValue = projectManager.getProject(projectId);
        mutableIssue.setProject(projectGenericValue);
        mutableIssue.setSummary(summary);
        mutableIssue.setOriginalEstimate(Long.decode(estimate));
        if (issueType == IssueHelper.SUBTASK_TYPE) {
            if (subTaskId == null) {
                Collection subTasksIssueTypes = subTaskManager.getSubTasksIssueTypes();
                Iterator subTaskIterator = subTasksIssueTypes.iterator();
                if (subTaskIterator.hasNext()) {
                    GenericValue genericValue = (GenericValue) subTasksIssueTypes.iterator().next();
                    subTaskId = String.valueOf(genericValue.get("id"));
                }
            }
            mutableIssue.setIssueTypeId(subTaskId);
        } else {
            mutableIssue.setIssueTypeId(String.valueOf(issueType));
        }

        User assigneeUser = null;
        try {
            assigneeUser = UserUtils.getUser(assignee);
            mutableIssue.setAssignee(assigneeUser);
        } catch (EntityNotFoundException e) {
            logger.warn("User not found", e);
        }

        mutableIssue.setDescription(description);
        updateIssue(mutableIssue);

        if (parentIssueKey != null) {
            MutableIssue parentMutableIssue = issueManager.getIssueObject(parentIssueKey);
            mutableIssue.setParentId(parentMutableIssue.getId());
        }

        Map params = new HashMap();
        params.put("issue", mutableIssue);

        GenericValue issue = null;
        try {
            issue = issueManager.createIssue(authenticationContext.getUser(), params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        MutableIssue createdMutableIssue = issueFactory.getIssue(issue);
        if (parentIssueKey != null) {
            MutableIssue parentMutableIssue = issueManager.getIssueObject(parentIssueKey);

            GenericValue parentIssueGenericValue = parentMutableIssue.getGenericValue();
            subTaskManager.createSubTaskIssueLink(parentIssueGenericValue, issue, assigneeUser);
        }

        return createdMutableIssue.getKey();
    }

    public void setProjectId(Long projectId) {
        this.projectId = projectId;
    }

    public void setComponents(ComponentsSystemField componentsSystemField) {
        this.componentsSystemField = componentsSystemField;
    }

    public void setAffectedVersions(AffectedVersionsSystemField affectedVersionsSystemField) {
        this.affectedVersionsSystemField = affectedVersionsSystemField;
    }

    public void setFixVersions(FixVersionsSystemField fixVersionsSystemField) {

        this.fixVersionsSystemField = fixVersionsSystemField;
    }

    protected void updateIssue(MutableIssue mutableIssue) {
        componentsSystemField.updateIssue(null, mutableIssue, customFieldValuesHolder);
        affectedVersionsSystemField.updateIssue(null, mutableIssue, customFieldValuesHolder);
        fixVersionsSystemField.updateIssue(null, mutableIssue, customFieldValuesHolder);
        prioritySystemField.updateIssue(null, mutableIssue, customFieldValuesHolder);
    }

    public void setCustomFieldValuesHolder(Map customFieldValuesHolder) {
        this.customFieldValuesHolder = customFieldValuesHolder;
    }

    public void setPriority(PrioritySystemField prioritySystemField) {
        this.prioritySystemField = prioritySystemField;
    }

    public void setIssueType(String issuetype) {
        this.setIssuetype(Integer.parseInt(issuetype));
    }

    public void init() throws Exception {

    }

    public void dispose() throws Exception {

    }

    public int getIssuetype() {
        return issuetype;
    }

    public void setIssuetype(int issuetype) {
        this.issuetype = issuetype;
    }
}
